package org.android.bbdroid.guiutils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

public final class Alerts {
	
	/* Dialog Alerts type ids */
	private static final int I = 13333;
	private static final int INPUT = 13336;
	private static final int MULTI_CHOICE = 13337;
	private static final int W = 13334;
	private static final int YES_NO = 13338;
	
	/* static map providing object exchange between methods calls */
	private static Map<String, Object> par = new HashMap<String, Object>();

	
	/* Specific base Listeners to retrieve input data from dialog alerts */

		/* Base input listener */
	public static abstract class AlertsInputOnClickListener<T extends Alerts.AlertsInputBase>
			implements DialogInterface.OnClickListener {
		private T input;

		protected T getInput() {
			return this.input;
		}

		void setInput(T t) {
			this.input = t;
		}
	}

		/* Base class implementing input data access */
	public static abstract class AlertsInputBase<T, S> implements Serializable {
		protected Map<Integer, T> data = new HashMap<Integer, T>();

		public abstract S get(int idx);

		void put(int idx, T value) {
			this.data.put(idx, value);
		}

		public int size() {
			return data.size();
		}
	}

		/* Boolean input access */
	public static final class AlertsInputBoolean extends
			Alerts.AlertsInputBase<Boolean, Boolean> {
		public AlertsInputBoolean() {
			super();
		}

		public Boolean get(int idx) {
			return this.data.get(idx);
		}
	}
		/* String input access */
	public static final class AlertsInputString extends
		Alerts.AlertsInputBase<EditText, String> {
		public AlertsInputString() {
			super();
		}

		public String get(int idx) {
			return ((EditText) this.data.get(idx)).getText().toString();
		}
	}	
	
		/* Base listener collecting input data, implementing classes MUST call super.onClick */
	public static class AlertsInputOnMultiChoiceClickListener implements
			DialogInterface.OnMultiChoiceClickListener {
		private Alerts.AlertsInputBoolean input;

		public void onClick(DialogInterface di, int which, boolean isChecked) {
			this.input.put(which, isChecked);
		}

		void setInput(Alerts.AlertsInputBoolean input) {
			this.input = input;
		}
	}
	
	/* Empty multichoice listener */
	public static final AlertsInputOnMultiChoiceClickListener NULL_MULTICHOICE_LISTENER = new AlertsInputOnMultiChoiceClickListener() {
		public void onClick(DialogInterface paramDialogInterface, int paramInt,
				boolean paramBoolean) {
			super.onClick(paramDialogInterface, paramInt, paramBoolean);
		}
	};
	
	/*Empty click listener with strings as input */
	public static final AlertsInputOnClickListener<AlertsInputString> NULL_ON_CLICK_LISTENER = new AlertsInputOnClickListener<AlertsInputString>() {
		public void onClick(DialogInterface paramDialogInterface, int paramInt) {
		}
	};
	/*Empty click listener with booleans as input */
	public static final AlertsInputOnClickListener<AlertsInputBoolean> NULL_ON_CLICK_LISTENER_B = new AlertsInputOnClickListener<AlertsInputBoolean>() {
		public void onClick(DialogInterface paramDialogInterface, int paramInt) {
		}
	};

	private static Bundle b = new Bundle();

	/* callback to be executed inside Activity's onCreateDialog */
	public static Dialog onCreateDialog(Context c, int id, Bundle params) {
		switch (id) {
		case I:
			return dialogOK(c, params.getCharSequence("title"),
					params.getCharSequence("message"),
					android.R.drawable.ic_dialog_info).create();
		case W:
			return dialogOK(c, params.getCharSequence("title"),
					params.getCharSequence("message"),
					android.R.drawable.ic_dialog_alert).create();
		case INPUT:
			CharSequence[] labels = b.getCharSequenceArray("labels");
			return input(
					c,
					params.getCharSequence("title"),
					params.getInt("icon"),
					(AlertsInputOnClickListener<AlertsInputString>) par
							.get("listener"),
					(AlertsInputString) par.get("inputs"), labels).create();
		case MULTI_CHOICE:
			return mchoice(
					c,
					params.getCharSequence("title"),
					params.getInt("icon"),
					params.getCharSequenceArray("mchoiceLabels"),
					params.getBooleanArray("mchoiceChecked"),
					(AlertsInputOnMultiChoiceClickListener) par
							.get("mlistener"),
					(AlertsInputOnClickListener<AlertsInputBoolean>) par
							.get("listener")).create();
		case YES_NO:
			return yesno(c, params.getCharSequence("title"),
					params.getCharSequence("message"),
					(DialogInterface.OnClickListener) par.get("listener"))
					.create();

		default:
			return null;
		}
	}

	private static AlertDialog.Builder dialogOK(Context paramContext,
			CharSequence title, CharSequence message, int icon) {
		AlertDialog.Builder builder = new AlertDialog.Builder(paramContext);
		builder.setMessage(message);
		builder.setTitle(title);
		builder.setIcon(icon);
		builder.setPositiveButton(android.R.string.ok, null);
		return builder;
	}

	public static void i(Activity a, int title, int message) {
		i(a, a.getString(title), a.getString(message));
	}

	public static void i(Activity a, CharSequence title, CharSequence message) {
		try {
			a.removeDialog(I);
		} catch (Exception e) // compatibility
		{
			e.printStackTrace();
		} finally {
			b = new Bundle();
			b.putCharSequence("title", title);
			b.putCharSequence("message", message);
			a.showDialog(I, b);
		}
	}

	private static AlertDialog.Builder input(Context c, CharSequence title,
			int icon, AlertsInputOnClickListener<AlertsInputString> l,
			AlertsInputString input, CharSequence[] labels) {
		AlertDialog.Builder builder = new AlertDialog.Builder(c);
		builder.setTitle(title);
		builder.setIcon(icon);
		LinearLayout layout = new LinearLayout(c);
		layout.setOrientation(LinearLayout.VERTICAL);
		layout.setWeightSum(1.0f);

		for (int i = 0; i < labels.length; i++) {
			CharSequence label = labels[i];
			TextView tv = new TextView(c);
			tv.setText(label);
			EditText et = new EditText(c);
			et.setSingleLine();
			input.put(i, et);
			layout.addView(tv);
			layout.addView(et);
		}

		builder.setView(layout);
		l.setInput(input);
		builder.setPositiveButton(android.R.string.ok, l);
		builder.setNegativeButton(android.R.string.cancel, l);
		return builder;
	}

	public static void input(Activity a, int title, int icon,
			AlertsInputOnClickListener<AlertsInputString> l, int[] labels) {
		String[] labelsStr = new String[labels.length];
		for (int i = 0; i < labelsStr.length; i++) {
			labelsStr[i] = a.getString(labels[i]);
		}
		input(a, a.getString(title), icon, l, labelsStr);
	}

	public static void input(Activity a, CharSequence title, int icon,
			AlertsInputOnClickListener<AlertsInputString> l,
			CharSequence[] labels) {
		try {
			a.removeDialog(INPUT);
			par.clear();
		} catch (Exception e) // for compatibility
		{
			e.printStackTrace();
		} finally {
			b = new Bundle();
			b.putCharSequence("title", title);
			b.putInt("icon", icon);
			b.putCharSequenceArray("labels", labels);
			par.put("listener", l == null ? NULL_ON_CLICK_LISTENER : l);
			
			par.put("inputs", new AlertsInputString()); 
			a.showDialog(INPUT, b);
		}
	}

	private static AlertDialog.Builder mchoice(Context c, CharSequence title,
			int icon, CharSequence[] labels, boolean[] checked,
			AlertsInputOnMultiChoiceClickListener ml,
			AlertsInputOnClickListener<AlertsInputBoolean> l) {
		AlertDialog.Builder builder = new AlertDialog.Builder(c);
		builder.setIcon(icon);
		builder.setTitle(title);
		builder.setMultiChoiceItems(labels, checked, ml);
		builder.setPositiveButton(android.R.string.ok, l);
		builder.setNegativeButton(android.R.string.cancel, l);

		AlertsInputBoolean input = new AlertsInputBoolean();

		for (int i = 0; i < labels.length; i++) {
			if (checked == null)
				input.put(i, false);
			else
				input.put(i, checked[i]);
		}
		ml.setInput(input);
		l.setInput(input);
		return builder;
	}

	public static void mchoice(Activity a, int title, int icon,
			CharSequence[] labels, boolean[] checked,
			AlertsInputOnMultiChoiceClickListener ml,
			AlertsInputOnClickListener<AlertsInputBoolean> l) {
		mchoice(a, a.getString(title), icon, labels, checked, ml, l);
	}

	public static void mchoice(Activity a, CharSequence title, int icon,
			CharSequence[] labels, boolean[] checked,
			AlertsInputOnMultiChoiceClickListener ml,
			AlertsInputOnClickListener<AlertsInputBoolean> l) {
		try {
			a.removeDialog(MULTI_CHOICE);
			par.clear();
		} catch (Exception e)// for compatibility
		{
			e.printStackTrace();
		} finally {
			b = new Bundle();
			b.putCharSequence("title", title);
			b.putInt("icon", icon);
			b.putCharSequenceArray("mchoiceLabels", labels);
			b.putBooleanArray("mchoiceChecked", checked);

			par.put("mlistener", ml == null ? NULL_MULTICHOICE_LISTENER : ml);
			par.put("listener", l == null ? NULL_ON_CLICK_LISTENER_B : l); 
			a.showDialog(MULTI_CHOICE, b);
		}
	}

	public static ProgressDialog prog(Context c, int title, int message,
			boolean indeterminate) {
		return prog(c, c.getString(title), c.getString(message), indeterminate);
	}

	public static ProgressDialog prog(Context c, CharSequence title,
			CharSequence message, boolean indeterminate) {
		return ProgressDialog.show(c, title, message, indeterminate);
	}

	public static void w(Activity a, int title, int message) {
		w(a, a.getString(title), a.getString(message));
	}

	public static void w(Activity a, CharSequence title, CharSequence message) {
		try {
			a.removeDialog(W);
			par.clear();
		} catch (Exception e) // for compatibility
		{
			e.printStackTrace();
		} finally {
			b = new Bundle();
			b.putCharSequence("title", title);
			b.putCharSequence("message", message);
			a.showDialog(W, b);
		}
	}

	private static AlertDialog.Builder yesno(Context c, CharSequence title,
			CharSequence message, DialogInterface.OnClickListener l) {
		AlertDialog.Builder builder = new AlertDialog.Builder(c);
		builder.setMessage(message);
		builder.setTitle(title);
		builder.setIcon(android.R.drawable.ic_dialog_alert);
		builder.setPositiveButton(android.R.string.ok, l);
		builder.setNegativeButton(android.R.string.cancel, l);
		return builder;
	}

	public static void yesno(Activity a, int title, int message,
			DialogInterface.OnClickListener l) {
		yesno(a, a.getString(title), a.getString(message), l);
	}

	public static void yesno(Activity a, CharSequence title,
			CharSequence message, DialogInterface.OnClickListener l) {
		try {
			a.removeDialog(YES_NO);
			par.clear();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			b = new Bundle();
			b.putCharSequence("title", title);
			b.putCharSequence("message", message);
			par.put("listener", l);
			a.showDialog(YES_NO, b);
		}
	}
}